package actions.movimientos;

import java.util.Date;
import java.util.List;

import services.entrega.EntregaService;
import services.movimiento.MovimientoCajaService;
import services.venta.VentaService;
import util.GSonHelper;
import util.SearchOperator;
import actions.base.BaseAction;

import com.google.gson.Gson;

import dto.ArqueoDTO;
import dto.EntregaDTO;
import dto.MovimientoCajaDTO;
import dto.SearchDTO;
import dto.VentaDTO;
import exceptions.CannotDeleteException;
import exceptions.CannotSaveException;
import exceptions.EntityNotFoundException;

public class MovimientosCajaAction extends BaseAction {
	
	private static final long serialVersionUID = 1L;

	private MovimientoCajaService movimientoCajaService;
	
	private VentaService ventaService;
	
	private EntregaService entregaService;
	
	private MovimientoCajaDTO movimientoCajaDTO;
	
	private ArqueoDTO arqueoDTO;
	
	private String query;
	
	private String idVenta;
	
	private String idEntrega;
	
	private Date fechaInicio;
	
	private Date fechaFin;
	
	
	@Override
	public String execute() {
		return SUCCESS;
	}
	
	/**
	 * Agrega un nuevo movimientoCaja
	 * @return
	 */
	public String agregar() {
		
		// TODO hacer validaciones
		

		String origen = movimientoCajaDTO.getOrigen();

		if ( !"AJUSTE".equals(origen) && !"ARQUEO".equals(origen) && idVenta.isEmpty() && idEntrega.isEmpty())  {
			
			setOk("false");
			setMensaje("El movimiento tiene que estar asociado a una venta o a una entrega");
			return SUCCESS_AGREGAR;
		}

		if ( !"AJUSTE".equals(origen) && !"ARQUEO".equals(origen) ) {
			
			// Venta asociada
			VentaDTO ventaDTO = null;
			if (!idVenta.isEmpty()) {
				try {
					ventaDTO = ventaService.findById(idVenta);
					Double montoVenta = ventaDTO.getFacturaDTO().getMonto();
					Double monto = (movimientoCajaDTO.getMonto() != null && movimientoCajaDTO.getMonto() != 0) ? movimientoCajaDTO.getMonto() : montoVenta;
					movimientoCajaDTO.setMonto(monto);
				} catch (EntityNotFoundException e) {
					setOk("false");
					setMensaje("La venta es INEXISTENTE");
					return SUCCESS_AGREGAR;
				}
			}
			// Entrega asociada	
			EntregaDTO entregaDTO = null;
			if (!idEntrega.isEmpty()) {
				try {
					entregaDTO = entregaService.findById(idEntrega);
					Double montoEntrega = entregaDTO.getCosto();
					Double monto = (movimientoCajaDTO.getMonto() != null && movimientoCajaDTO.getMonto() != 0) ? movimientoCajaDTO.getMonto() : montoEntrega;
					movimientoCajaDTO.setMonto(monto);
				} catch (EntityNotFoundException e) {
					setOk("false");
					setMensaje("La entrega es INEXISTENTE");
					return SUCCESS_AGREGAR;
				}
			}
			
			try {
				movimientoCajaDTO.setVentaDTO(ventaDTO);
				movimientoCajaDTO.setEntregaDTO(entregaDTO);
				movimientoCajaService.save(movimientoCajaDTO);
			} catch (CannotSaveException e) {
				setOk("false");
				setMensaje("No se ha podido almacenar el movimiento de caja");
				return SUCCESS_AGREGAR;
			}
			setOk("true");
			setMensaje("El movimiento de caja se ha almacenado correctamente");
			return SUCCESS_AGREGAR;
		}
		
		if ("AJUSTE".equals(origen)) {
			try {
				movimientoCajaService.save(movimientoCajaDTO);
				setOk("true");
				setMensaje("El movimiento de caja se ha almacenado correctamente");
				return SUCCESS_AGREGAR;
			} catch (CannotSaveException e) {
				setOk("false");
				setMensaje("No se ha podido almacenar el movimiento de caja");
				return SUCCESS_AGREGAR;
			}
		}
		
		if ("ARQUEO".equals(origen)) {
			try {
				movimientoCajaDTO.setArqueoDTO(arqueoDTO);
				movimientoCajaService.save(movimientoCajaDTO);
				setOk("true");
				setMensaje("El movimiento de caja se ha almacenado correctamente");
				return SUCCESS_AGREGAR;
			} catch (CannotSaveException e) {
				setOk("false");
				setMensaje("No se ha podido almacenar el movimiento de caja");
				return SUCCESS_AGREGAR;
			}
		}
			
		setOk("false");
		setMensaje("No se ha guardado ningun movimiento de caja");
		return SUCCESS_AGREGAR;
	}
	
	/**
	 * Borra un movimientoCaja
	 * @return
	 */
	public String borrar() {
		
		// TODO hacer validacion sobre ID
		
		try {
			movimientoCajaService.delete(id);
		} catch (CannotDeleteException e) {
			setOk("false");
			setMensaje("El movimientoCaja no se ha podido eliminar");
			return SUCCESS_AGREGAR;
		}
		setOk("true");
		setMensaje("El movimientoCaja se ha eliminado correctamente");
		return SUCCESS_AGREGAR;
	}

	/**
	 * Obtiene una lista de todos los movimientoCajas
	 * @return	la lista
	 */
	public String getMovimientoCajas() {

		List<MovimientoCajaDTO> movimientoCajas = movimientoCajaService.findAll("id", false);
		
		Gson gson = GSonHelper.getInstance();
		String movimientoCajasStr = gson.toJson(movimientoCajas);
		
		setLista(movimientoCajasStr);
		return SUCCESS_LISTADO;
	}
	
	/**
	 * Obtiene un movimientoCaja
	 * @return el movimientoCaja
	 */
	public String getMovimientoCaja() {
		
		// TODO validacion sobre ID
		
		MovimientoCajaDTO movimientoCaja = movimientoCajaService.findById(id);
		
		Gson gson = GSonHelper.getInstance();
		String movimientoCajaStr = gson.toJson(movimientoCaja);
		setLista(movimientoCajaStr);
		return SUCCESS_JSON;
	}
	
	/**
	 * Obtiene una lista de movimientoCajas para mostrar en un listado 'typeahead'
	 * @return	la lista json
	 */
	public String getMovimientoCajaList() {
		
		SearchDTO searchDTO = new SearchDTO();
		searchDTO.addCriteria("descripcion", getQuery(), SearchOperator.LIKE);
		
		List<MovimientoCajaDTO> movimientoCajas = movimientoCajaService.search(searchDTO);
		
		Gson gson = GSonHelper.getInstance();
		String movimientoCajasStr = gson.toJson(movimientoCajas);
		
		setLista(movimientoCajasStr);
		return SUCCESS_LISTADO;
	}

	
	/**
	 * Busca movimientoCajas
	 */
	public String buscar() {
		
		// TODO validacion sobre DTO
		
		SearchDTO searchDTO = new SearchDTO();
		searchDTO.addBeetwenCriteria("fecha", fechaInicio, fechaFin);
		
		List<MovimientoCajaDTO> movimientoCajas = movimientoCajaService.search(searchDTO);
		
		Gson gson = GSonHelper.getInstance();
		String movimientoCajasStr = gson.toJson(movimientoCajas);
		
		setLista(movimientoCajasStr);
		return SUCCESS_LISTADO;
	}
	
	
	/**
	 * Getters & Setters
	 */
	public MovimientoCajaDTO getMovimientoCajaDTO() {
		return movimientoCajaDTO;
	}

	public String getQuery() {
		return query;
	}

	public void setQuery(String query) {
		this.query = query;
	}
	
	public String getIdVenta() {
		return idVenta;
	}

	public void setIdVenta(String idVenta) {
		this.idVenta = idVenta;
	}

	public String getIdEntrega() {
		return idEntrega;
	}

	public void setIdEntrega(String idEntrega) {
		this.idEntrega = idEntrega;
	}
	
	public ArqueoDTO getArqueoDTO() {
		return arqueoDTO;
	}

	public void setArqueoDTO(ArqueoDTO arqueoDTO) {
		this.arqueoDTO = arqueoDTO;
	}

	public void setMovimientoCajaDTO(MovimientoCajaDTO movimientoCajaDTO) {
		this.movimientoCajaDTO = movimientoCajaDTO;
	}

	public VentaService getVentaService() {
		return ventaService;
	}

	public void setVentaService(VentaService ventaService) {
		this.ventaService = ventaService;
	}

	public EntregaService getEntregaService() {
		return entregaService;
	}

	public void setEntregaService(EntregaService entregaService) {
		this.entregaService = entregaService;
	}

	public MovimientoCajaService getMovimientoCajaService() {
		return movimientoCajaService;
	}

	public void setMovimientoCajaService(MovimientoCajaService movimientoCajaService) {
		this.movimientoCajaService = movimientoCajaService;
	}

	public Date getFechaInicio() {
		return fechaInicio;
	}

	public void setFechaInicio(Date fechaInicio) {
		this.fechaInicio = fechaInicio;
	}

	public Date getFechaFin() {
		return fechaFin;
	}

	public void setFechaFin(Date fechaFin) {
		this.fechaFin = fechaFin;
	}

}
